// Copyright 2013 Vedran Vuk. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package netutil provides some utilities for the net package.
package netutil

import (
	"net"
)

func makeUint16(lo, hi byte) uint16 {
	return uint16(lo) | uint16(hi) << 8
}

func makeBytes(u uint16) (lo, hi byte) {
	return byte(u), byte(u >> 8)
}

func prevIP4(ip net.IP) net.IP {
	c := make([]byte, 4)
	copy(c, ip[0:])
	i := 3
	for {
		if c[i] > 0 {
			c[i]--
			break
		}
		c[i] = 255
		i--
		if i < 0 {
			break
		}
	}
	return c
}

func nextIP4(ip net.IP) net.IP {
	c := make([]byte, 4)
	copy(c, ip[0:])
	i := 3
	for {
		if c[i] < 255 {
			c[i]++
			break
		}
		c[i] = 0
		i--
		if i < 0 {
			break
		}
	}
	return c
}

func prevIP6(ip net.IP) net.IP {
	c := make([]byte, 16)
	copy(c, ip[0:])
	i := 7
	for {
		w := makeUint16(c[i*2+1], c[i*2])
		if w > 0x0000 {
			w--
			c[i*2+1], c[i*2] = makeBytes(w)
			break
		}
		c[i*2], c[i*2+1] = 0xFF, 0xFF
		i--
		if i < 0 {
			break
		}
	}
	return c
}

func nextIP6(ip net.IP) net.IP {
	c := make([]byte, 16)
	copy(c, ip[0:])
	i := 7
	for {
		w := makeUint16(c[i*2+1], c[i*2])
		if w < 0xFFFF {
			w++
			c[i*2+1], c[i*2] = makeBytes(w)
			break
		}
		c[i*2], c[i*2+1] = 0x00, 0x00
		i--
		if i < 0 {
			break
		}
	}
	return c
}

// Returns a new IP with an address that follows "ip". Wraps around.
func PrevIP(ip net.IP) net.IP {
	if t := ip.To4(); t != nil {
		return prevIP4(t)
	}
	return prevIP6(ip)
}

// Returns a new IP with an address that precedes "ip". Wraps around.
func NextIP(ip net.IP) net.IP {
	if t := ip.To4(); t != nil {
		return nextIP4(t)
	}
	return nextIP6(ip)
}
